package config

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"os"
	"regexp"
	"runtime"
)

// RawSection 一个帮助configuration切割文本的helper
type RawSection struct {
	name   string
	kvstrs []string
}

// Name 返回section的名字
func (raw *RawSection) Name() string {
	return raw.name
}

// KvStrings 返回section下的kv字符串
func (raw *RawSection) KvStrings() []string {
	return raw.kvstrs
}

var (
	defaultSeperation = '\n'
	commentRegExp     = "# .*"
	sectionRegExp     = "\\[[a-zA-Z0-9]*\\]"
	keyValRegExp      = ".* = .*"
	emptyLineRegExp   = "^(\\s*)\\n"
)

func init() {
	// 根据系统类型来选择默认的注释模式
	if runtime.GOOS == "windows" {
		commentRegExp = "; .*"
		emptyLineRegExp = "^(\\s*)\\r\\n"
	}
}

// Parse 根据 file 进行 parse分析
// 错误会回传给上级，由上级决定
func Parse(fileName string) ([]*RawSection, error) {
	// 打开文件
	file, err := os.Open(fileName)
	if err != nil {
		return nil, err
	}
	defer file.Close() // 延迟关闭

	var conf []*RawSection

	//创建Reader对象
	BufReader := bufio.NewReader(file)
	line := 0
	for {
		var lastLine bool = false
		bytes, err := BufReader.ReadBytes(byte(defaultSeperation))
		if err != nil {
			if err == io.EOF {
				lastLine = true
				if len(bytes) == 0 {
					// 代表最后一行是空行
					break
				}
			} else {
				return nil, err
			}
		}
		line++

		if matched, _ := regexp.MatchString(emptyLineRegExp, string(bytes)); matched {
			// 匹配到空行
			continue
		}

		if matched, _ := regexp.MatchString(commentRegExp, string(bytes)); matched {
			// 如果匹配到注释，跳过即可
			continue
		}

		// 判断是否是section
		if matched, _ := regexp.MatchString(sectionRegExp, string(bytes)); matched {
			// 如果匹配到section
			confSec := new(RawSection)
			confSec.name = string(bytes[1 : len(bytes)-2])
			conf = append(conf, confSec)
			continue
		}

		// 如果都没有匹配到，那么当前应该有一个section
		// 如果没有则添加一个默认section，否则以最后一个section为iesection
		if len(conf) == 0 {
			// 添加默认section
			confSec := new(RawSection)
			confSec.name = "default"
			conf = append(conf, confSec)
		}
		// 拿出最近的section
		curSection := conf[len(conf)-1]
		// spt := strings.Split(string(bytes), " = ")
		if matched, _ := regexp.MatchString(keyValRegExp, string(bytes)); !matched {
			// 代表不符合 ". = ."的格式
			info := fmt.Sprintf("parse exit in line[%d]: %s", line, string(bytes))
			return nil, errors.New(info)
		}
		if !lastLine {
			// 如果不是最后一行，会有DefaultSeperation
			bytes = bytes[:len(bytes)-1]
		}
		curSection.kvstrs = append(curSection.kvstrs, string(bytes))

		if lastLine {
			break
		}
	}
	return conf, nil
}
